package repository

import (
	"container/list"
	"context"
	"fmt"
	"sync"
	"time"
)

type memoryCacheProvider struct {
	mu       sync.RWMutex
	items    map[string]*cacheItem
	indexes  map[string]map[string]map[interface{}]struct{} // indexName -> indexValue -> primaryKeys
	lruList  *list.List
	ttl      time.Duration
	maxItems int
	stats    CacheStats
}

type cacheItem struct {
	key        string
	value      interface{}
	expiration time.Time
	lruElement *list.Element
}

func NewMemoryCacheProvider(maxItems int, ttl time.Duration) *memoryCacheProvider {
	return &memoryCacheProvider{
		items:    make(map[string]*cacheItem),
		indexes:  make(map[string]map[string]map[interface{}]struct{}),
		lruList:  list.New(),
		ttl:      ttl,
		maxItems: maxItems,
	}
}

func (m *memoryCacheProvider) Set(ctx context.Context, key string, value interface{}) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 检查是否已存在
	if item, exists := m.items[key]; exists {
		// 更新值和过期时间
		item.value = value
		item.expiration = time.Now().Add(m.ttl)
		// 移动到LRU列表前端
		m.lruList.MoveToFront(item.lruElement)
		return nil
	}

	// 检查是否需要淘汰
	if m.maxItems > 0 && len(m.items) >= m.maxItems {
		m.evict(1)
	}

	// 创建新项
	expiration := time.Now().Add(m.ttl)
	element := m.lruList.PushFront(key)
	item := &cacheItem{
		key:        key,
		value:      value,
		expiration: expiration,
		lruElement: element,
	}

	m.items[key] = item
	m.stats.Size = int64(len(m.items))
	return nil
}

func (m *memoryCacheProvider) Get(ctx context.Context, key string) (interface{}, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	item, exists := m.items[key]
	if !exists {
		m.stats.Misses++
		return nil, nil
	}

	if time.Now().After(item.expiration) {
		m.stats.Misses++
		m.stats.Expired++
		return nil, nil
	}

	m.stats.Hits++
	return item.value, nil
}

func (m *memoryCacheProvider) Delete(ctx context.Context, key string) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	item, exists := m.items[key]
	if !exists {
		return nil
	}

	// 从LRU列表中移除
	m.lruList.Remove(item.lruElement)
	// 从主存储中移除
	delete(m.items, key)
	m.stats.Size = int64(len(m.items))
	return nil
}

// AddToIndex 添加值到索引
func (m *memoryCacheProvider) AddToIndex(ctx context.Context, indexName, indexValue string, primaryKey interface{}) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 初始化索引结构
	if _, ok := m.indexes[indexName]; !ok {
		m.indexes[indexName] = make(map[string]map[interface{}]struct{})
	}
	if _, ok := m.indexes[indexName][indexValue]; !ok {
		m.indexes[indexName][indexValue] = make(map[interface{}]struct{})
	}

	// 添加主键到索引
	m.indexes[indexName][indexValue][primaryKey] = struct{}{}
	return nil
}

// GetFromIndex 从索引获取值
func (m *memoryCacheProvider) GetFromIndex(ctx context.Context, indexName, indexValue string) ([]interface{}, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 获取索引下的所有主键
	index, ok := m.indexes[indexName]
	if !ok {
		return nil, nil
	}

	primaryKeys, ok := index[indexValue]
	if !ok {
		return nil, nil
	}

	// 收集所有有效值
	var results []interface{}
	for pk := range primaryKeys {
		pkStr := fmt.Sprintf("%v", pk)
		if item, exists := m.items[pkStr]; exists && !time.Now().After(item.expiration) {
			results = append(results, item.value)
		}
	}

	return results, nil
}

// RemoveFromIndex 从索引移除值
func (m *memoryCacheProvider) RemoveFromIndex(ctx context.Context, indexName, indexValue string, primaryKey interface{}) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 检查索引是否存在
	index, ok := m.indexes[indexName]
	if !ok {
		return nil
	}

	// 从索引值中移除主键
	primaryKeys, ok := index[indexValue]
	if !ok {
		return nil
	}

	delete(primaryKeys, primaryKey)

	// 如果索引值没有主键了，删除该索引值
	if len(primaryKeys) == 0 {
		delete(index, indexValue)
	}

	// 如果索引没有值了，删除整个索引
	if len(index) == 0 {
		delete(m.indexes, indexName)
	}

	return nil
}
